﻿#region Copyright ©2008-2010, Technische Universitaet Muenchen

// ====================================================================================================
//
// Last Changed by       $Author: then $
// Last Changed Date     $LastChangedDate: 2009-12-16 16:37:27 +0100 (Wed, 16 Dec 2009) $
// Last Changed Revision $Rev: 504 $
//
// ====================================================================================================

#endregion

#region

using System;
using System.Collections.Generic;

#endregion

namespace Tum.CollabXT
{

    #region Interfaces

    public interface IAssociation
    {
        /// <summary>
        /// Id of the association.
        /// </summary>
        string Id { get; set; }

        /// <summary>
        /// Name of the association.
        /// </summary>
        string Name { get; set; }

        /// <summary>
        /// Description of the association.
        /// </summary>
        string Description { get; set; }

        /// <summary>
        /// Storage for content of any type.
        /// To be used for internal temporary variables or as way to pass information from one tool provider to another.
        /// Additionally, data can be stored that is not recognized by all providers, but by some.
        /// </summary>
        Dictionary<string, object> ExtendedData { get; }


        /// <summary>
        /// Identifier of the element this association orinated from.
        /// </summary>
        string SourceId { get; }

        /// <summary>
        /// Identifier of the element this association goes to.
        /// </summary>
        string DestinationId { get; }


        /// <summary>
        /// Type of the source element.
        /// </summary>
        Type SourceType { get; }

        /// <summary>
        /// Type of the destination element.
        /// </summary>
        Type DestinationType { get; }
    }

    #endregion

    #region Attributes

    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
    public class AssociationKindAttribute : Attribute
    {
        public AssociationType AssociationType { get; private set; }

        public AssociationDirection AssociationDirection { get; private set; }

        public AssociationKindAttribute(AssociationType type, AssociationDirection direction)
        {
            AssociationType = type;
            AssociationDirection = direction;
        }
    }

    public enum AssociationDirection
    {
        Directed,
        Undirected,
        Miscellaneous,
    }

    public enum AssociationType
    {
        Relation,
        Dependency,
        Composition,
        Miscellaneous,
    }

    #endregion

    public class Association<TSource, TDestination> : IAssociation where TSource : class, IProcessElement where TDestination : class, IProcessElement
    {
        #region Private Attributes

        private readonly Dictionary<string, object> _ExtendedData = new Dictionary<string, object>();

        #endregion

        #region IAssociation Members

        public string Id { get; set; }

        public string Name { get; set; }

        /// <summary>
        /// Storage for content of any type.
        /// To be used for internal temporary variables or as way to pass information from one tool provider to another.
        /// Additionally, data can be stored that is not recognized by all providers, but by some.
        /// </summary>
        public Dictionary<string, object> ExtendedData
        {
            get { return _ExtendedData; }
        }

        /// <summary>
        /// Identifier of the element this association orinated from.
        /// </summary>
        public string SourceId
        {
            get { return Source.Id; }
        }

        /// <summary>
        /// Identifier of the element this association goes to.
        /// </summary>
        public string DestinationId
        {
            get { return Destination.Id; }
        }

        public Type SourceType
        {
            get { return typeof (TSource); }
        }

        public Type DestinationType
        {
            get { return typeof (TDestination); }
        }

        /// <summary>
        /// Description of the association.
        /// </summary>
        public string Description { get; set; }

        #endregion

        #region Public Properties

        private TSource _Source;

        public TSource Source
        {
            get { return _Source; }
            set
            {
                if (value == null)
                    throw new ArgumentNullException();
                _Source = value;
            }
        }

        private TDestination _Destination;

        public TDestination Destination
        {
            get { return _Destination; }
            set
            {
                if (value == null)
                    throw new ArgumentNullException();
                _Destination = value;
            }
        }

        #endregion

        #region ctor/dtor

        public Association(TSource from, TDestination to)
        {
            Source = from;
            Destination = to;
        }

        #endregion

        #region Public methods

        public static IAssociation Create(Type associationType, IProcessElement processElementSource, IProcessElement processElementDestination)
        {
            ///TODO: !!!!
            throw new NotImplementedException();
        }

        #endregion
    }


    /// <summary>
    /// Dependency between a task and its parent activity.
    /// </summary>
    [AssociationKind(AssociationType.Composition, AssociationDirection.Directed)]
    public class TaskToActivity : Association<ITask, IActivity>
    {
        public TaskToActivity(ITask task, IActivity activity)
            : base(task, activity)
        {
        }
    }

    /// <summary>
    /// Dependency between a milestone and its predecessor.
    /// </summary>
    [AssociationKind(AssociationType.Dependency, AssociationDirection.Directed)]
    public class MilestoneToPredecessor : Association<IMilestone, IMilestone>
    {
        public MilestoneToPredecessor(IMilestone milestone, IMilestone predecessor)
            : base(milestone, predecessor)
        {
        }
    }

    /// <summary>
    /// Dependency between an activity and its parent activity.
    /// </summary>
    [AssociationKind(AssociationType.Composition, AssociationDirection.Directed)]
    public class ActivityToSubActivity : Association<IActivity, IActivity>
    {
        public ActivityToSubActivity(IActivity parentActivity, IActivity subActivity)
            : base(parentActivity, subActivity)
        {
        }
    }

    /// <summary>
    /// Dependency between an artifact and its discipline.
    /// </summary>
    [AssociationKind(AssociationType.Relation, AssociationDirection.Undirected)]
    public class ArtifactToDiscipline : Association<IArtifact, IDiscipline>
    {
        /// <summary>
        /// Constructor.
        /// </summary>
        public ArtifactToDiscipline(IArtifact artifact, IDiscipline discipline)
            : base(artifact, discipline)
        {
        }
    }

    /// <summary>
    /// Dependency between a product and a participating role.
    /// </summary>
    [AssociationKind(AssociationType.Relation, AssociationDirection.Undirected)]
    public class RoleToArtifact : Association<IRole, IArtifact>
    {
        /// <summary>
        /// Constructor.
        /// </summary>
        public RoleToArtifact(IRole role, IArtifact artifact) : base(role, artifact)
        {
        }
    }

    /// <summary>
    /// Dependency between a product and a role responsible for it.
    /// </summary>
    [AssociationKind(AssociationType.Relation, AssociationDirection.Undirected)]
    public class RoleIsResponsibleForArtifact : RoleToArtifact
    {
        /// <summary>
        /// Constructor.
        /// </summary>
        public RoleIsResponsibleForArtifact(IRole role, IArtifact artifact)
            : base(role, artifact)
        {
        }
    }

    /// <summary>
    /// Dependency between a product and a role responsible for it.
    /// </summary>
    [AssociationKind(AssociationType.Relation, AssociationDirection.Undirected)]
    public class RoleIsParticipatingInArtifact : RoleToArtifact
    {
        /// <summary>
        /// Constructor.
        /// </summary>
        public RoleIsParticipatingInArtifact(IRole role, IArtifact artifact)
            : base(role, artifact)
        {
        }
    }

    /// <summary>
    /// Dependency between a milestone and a belonging product.
    /// </summary>
    [AssociationKind(AssociationType.Composition, AssociationDirection.Directed)]
    public class ArtifactToMilestone : Association<IArtifact, IMilestone>
    {
        /// <summary>
        /// Constructor.
        /// </summary>
        public ArtifactToMilestone(IArtifact artifact, IMilestone milestone) : base(artifact, milestone)
        {
        }
    }

    /// <summary>
    /// Dependency between an activity and a belonging artifact.
    /// </summary>
    [AssociationKind(AssociationType.Relation, AssociationDirection.Undirected)]
    public class ActivityToArtifact : Association<IActivity, IArtifact>
    {
        /// <summary>
        /// Constructor.
        /// </summary>
        public ActivityToArtifact(IActivity activity, IArtifact artifact)
            : base(activity, artifact)
        {
        }
    }

    /// <summary>
    /// Dependency between an activity and a belonging role.
    /// </summary>
    [AssociationKind(AssociationType.Relation, AssociationDirection.Undirected)]
    public class ActivityToRole : Association<IActivity, IRole>
    {
        /// <summary>
        /// Constructor.
        /// </summary>
        public ActivityToRole(IActivity activity, IRole role)
            : base(activity, role)
        {
        }
    }

    /// <summary>
    /// Dependency between a task and a belonging role.
    /// </summary>
    [AssociationKind(AssociationType.Relation, AssociationDirection.Undirected)]
    public class TaskToRole : Association<ITask, IRole>
    {
        /// <summary>
        /// Constructor.
        /// </summary>
        public TaskToRole(ITask task, IRole role)
            : base(task, role)
        {
        }
    }


    /// <summary>
    /// Defines a product to product dependency
    /// </summary>
    [AssociationKind(AssociationType.Dependency, AssociationDirection.Directed)]
    public class ArtifactToArtifact : Association<IArtifact, IArtifact>
    {
        /// <summary>
        /// Constructor.
        /// </summary>
        public ArtifactToArtifact(IArtifact artifact, IArtifact dependentArtifact)
            : base(artifact, dependentArtifact)
        {
        }
    }

    /// <summary>
    /// Dependency between a product and another that is contextually dependent.
    /// </summary>
    [AssociationKind(AssociationType.Dependency, AssociationDirection.Directed)]
    public class ContentDependency : ArtifactToArtifact
    {
        /// <summary>
        /// Constructor.
        /// </summary>
        public ContentDependency(IArtifact artifact, IArtifact dependentArtifact)
            : base(artifact, dependentArtifact)
        {
        }
    }

    /// <summary>
    /// Dependency between a product and another one of which the generation is depending on the first.
    /// </summary>
    [AssociationKind(AssociationType.Dependency, AssociationDirection.Directed)]
    public class GenerationDependency : ArtifactToArtifact
    {
        /// <summary>
        /// Constructor.
        /// </summary>
        public GenerationDependency(IArtifact artifact, IArtifact dependentArtifact)
            : base(artifact, dependentArtifact)
        {
        }
    }

    /// <summary>
    /// Dependency between a product and another that is a part of the first.
    /// </summary>
    [AssociationKind(AssociationType.Dependency, AssociationDirection.Directed)]
    public class CompositionDependency : ArtifactToArtifact
    {
        /// <summary>
        /// Constructor.
        /// </summary>
        public CompositionDependency(IArtifact artifact, IArtifact dependentArtifact)
            : base(artifact, dependentArtifact)
        {
        }
    }

    /// <summary>
    /// Dependency between a topic and an artifact.
    /// </summary>
    [AssociationKind(AssociationType.Relation, AssociationDirection.Undirected)]
    public class TopicToArtifact : Association<ITopic, IArtifact>
    {
        /// <summary>
        /// Constructor.
        /// </summary>
        public TopicToArtifact(ITopic topic, IArtifact artifact)
            : base(topic, artifact)
        {
        }
    }

    /// <summary>
    /// Dependency between a topic and its sub-topic.
    /// </summary>
    [AssociationKind(AssociationType.Composition, AssociationDirection.Directed)]
    public class TopicToSubTopic : Association<ITopic, ITopic>
    {
        /// <summary>
        /// Constructor
        /// </summary>
        public TopicToSubTopic(ITopic parentTopic, ITopic childTopic)
            : base(parentTopic, childTopic)
        {
        }
    }
}